package com.ruoyi.inventory.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import com.ruoyi.common.utils.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.inventory.mapper.TWarehouseStockMapper;
import com.ruoyi.inventory.domain.TWarehouseStock;
import com.ruoyi.inventory.service.ITWarehouseStockService;

/**
 * 库存Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-09-24
 */
@Service
public class TWarehouseStockServiceImpl implements ITWarehouseStockService 
{
    private static final Logger log = LoggerFactory.getLogger(TWarehouseStockServiceImpl.class);
    
    @Autowired
    private TWarehouseStockMapper tWarehouseStockMapper;

    /**
     * 查询库存
     * 
     * @param id 库存主键
     * @return 库存
     */
    @Override
    public TWarehouseStock selectTWarehouseStockById(Long id)
    {
        return tWarehouseStockMapper.selectTWarehouseStockById(id);
    }

    /**
     * 查询库存列表
     * 
     * @param tWarehouseStock 库存
     * @return 库存
     */
    @Override
    public List<TWarehouseStock> selectTWarehouseStockList(TWarehouseStock tWarehouseStock)
    {
        return tWarehouseStockMapper.selectTWarehouseStockList(tWarehouseStock);
    }

    /**
     * 新增库存
     * 
     * @param tWarehouseStock 库存
     * @return 结果
     */
    @Override
    public int insertTWarehouseStock(TWarehouseStock tWarehouseStock)
    {
        tWarehouseStock.setCreatedAt(DateUtils.getNowDate());
        tWarehouseStock.setUpdatedAt(DateUtils.getNowDate());
        return tWarehouseStockMapper.insertTWarehouseStock(tWarehouseStock);
    }

    /**
     * 使用悲观锁更新库存 - 核心方法
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateStockWithPessimisticLock(String warehouseCode, String partNo, 
                                            BigDecimal quantity, String txType) {
        log.info("开始悲观锁库存更新: warehouseCode={}, partNo={}, quantity={}, txType={}", 
                warehouseCode, partNo, quantity, txType);
        
        try {
            // 构建查询条件
            TWarehouseStock query = new TWarehouseStock();
            query.setWarehouseCode(warehouseCode);
            query.setPartNo(partNo);
            query.setIsDelete(0);
            
            // 使用FOR UPDATE锁定特定行
            TWarehouseStock stock = tWarehouseStockMapper.selectForUpdate(query);
            
            if (stock != null) {
                // 在锁保护下计算新库存
                BigDecimal currentQuantity = stock.getQuantity() != null ? stock.getQuantity() : BigDecimal.ZERO;
                BigDecimal newQuantity;
                
                if ("INBOUND".equals(txType)) {
                    // 入库：增加库存数量
                    newQuantity = currentQuantity.add(quantity);
                    log.info("入库操作: 当前库存={}, 入库数量={}, 新库存={}", 
                            currentQuantity, quantity, newQuantity);
                } else {
                    // 出库：减少库存数量
                    newQuantity = currentQuantity.subtract(quantity);
                    if (newQuantity.compareTo(BigDecimal.ZERO) < 0) {
                        throw new RuntimeException(String.format("库存不足！当前库存：%s，出库数量：%s", 
                                currentQuantity, quantity));
                    }
                    log.info("出库操作: 当前库存={}, 出库数量={}, 新库存={}", 
                            currentQuantity, quantity, newQuantity);
                }
                
                // 更新库存（在锁保护下）
                stock.setQuantity(newQuantity);
                stock.setUpdatedAt(new Date());
                int result = tWarehouseStockMapper.updateTWarehouseStock(stock);
                
                log.info("悲观锁库存更新完成: 影响行数={}", result);
                return result;
            } else {
                // 库存记录不存在时的处理
                if ("INBOUND".equals(txType)) {
                    // 入库时创建新记录
                    int result = createNewStockRecord(warehouseCode, partNo, quantity);
                    log.info("创建新库存记录: 影响行数={}", result);
                    return result;
                } else {
                    // 出库时记录不存在
                    throw new RuntimeException("库存记录不存在，无法出库");
                }
            }
        } catch (Exception e) {
            log.error("悲观锁库存更新失败: warehouseCode={}, partNo={}, quantity={}, txType={}", 
                     warehouseCode, partNo, quantity, txType, e);
            throw e;
        }
    }
    
    /**
     * 创建新库存记录
     */
    private int createNewStockRecord(String warehouseCode, String partNo, BigDecimal quantity) {
        TWarehouseStock newStock = new TWarehouseStock();
        newStock.setWarehouseCode(warehouseCode);
        newStock.setPartNo(partNo);
        newStock.setQuantity(quantity);
        newStock.setIsDelete(0);
        newStock.setCreatedAt(new Date());
        newStock.setUpdatedAt(new Date());
        
        return tWarehouseStockMapper.insertTWarehouseStock(newStock);
    }

    /**
     * 修改库存
     * 
     * @param tWarehouseStock 库存
     * @return 结果
     */
    @Override
    public int updateTWarehouseStock(TWarehouseStock tWarehouseStock)
    {
        tWarehouseStock.setUpdatedAt(DateUtils.getNowDate());
        return tWarehouseStockMapper.updateTWarehouseStock(tWarehouseStock);
    }

    /**
     * 批量删除库存
     * 
     * @param ids 需要删除的库存主键
     * @return 结果
     */
    @Override
    public int deleteTWarehouseStockByIds(Long[] ids)
    {
        return tWarehouseStockMapper.deleteTWarehouseStockByIds(ids);
    }

    /**
     * 删除库存信息
     * 
     * @param id 库存主键
     * @return 结果
     */
    @Override
    public int deleteTWarehouseStockById(Long id)
    {
        return tWarehouseStockMapper.deleteTWarehouseStockById(id);
    }

    /**
     * 根据盘点结果调整库存
     * 
     * @param warehouseCode 仓库编码
     * @param partNo 备件编号
     * @param adjustmentQuantity 调整数量（正数为盘盈，负数为盘亏）
     * @param remark 备注
     * @return 结果
     */
    @Override
    public int adjustStockByInventory(String warehouseCode, String partNo, BigDecimal adjustmentQuantity, String remark)
    {
        // 查询现有库存记录
        TWarehouseStock stockQuery = new TWarehouseStock();
        stockQuery.setWarehouseCode(warehouseCode);
        stockQuery.setPartNo(partNo);
        stockQuery.setIsDelete(0);
        
        List<TWarehouseStock> existingStocks = tWarehouseStockMapper.selectTWarehouseStockList(stockQuery);
        
        if (existingStocks != null && !existingStocks.isEmpty()) {
            // 更新现有库存记录
            TWarehouseStock existingStock = existingStocks.get(0);
            BigDecimal currentQuantity = existingStock.getQuantity() != null ? existingStock.getQuantity() : BigDecimal.ZERO;
            
            // 根据调整数量更新库存
            BigDecimal newQuantity = currentQuantity.add(adjustmentQuantity);
            if (newQuantity.compareTo(BigDecimal.ZERO) < 0) {
                newQuantity = BigDecimal.ZERO; // 库存不能为负数
            }
            
            existingStock.setQuantity(newQuantity);
            existingStock.setUpdatedAt(new Date());
            return tWarehouseStockMapper.updateTWarehouseStock(existingStock);
        } else {
            // 如果库存记录不存在，创建新记录（仅当调整数量为正数时）
            if (adjustmentQuantity.compareTo(BigDecimal.ZERO) > 0) {
                TWarehouseStock newStock = new TWarehouseStock();
                newStock.setWarehouseCode(warehouseCode);
                newStock.setPartNo(partNo);
                newStock.setQuantity(adjustmentQuantity);
                newStock.setIsDelete(0);
                newStock.setCreatedAt(new Date());
                newStock.setUpdatedAt(new Date());
                return tWarehouseStockMapper.insertTWarehouseStock(newStock);
            }
        }
        
        return 0;
    }
}
